module sram(
    input clk,
    input rst_n,

    inout [15:0] sram_data,
    output [18:0] sram_addr,
    output sram_oe_n,
    output sram_wr_n,
    output sram_lb_n,
    output sram_ub_n,

    input mem_valid,
    input [3:0] mem_wstrb,
    input [31:0] mem_addr,
    input [31:0] mem_wdata,
    output [31:0] mem_rdata,
    output mem_ready
);
reg [15:0] sram_wdata;
assign sram_data = (wr == 'b1) ? sram_wdata : 'hzzzz;

reg wr;
assign sram_wr_n = ~wr;

reg sram_oe;
assign sram_oe_n = ~sram_oe;

reg [1:0] sram_mask;
assign sram_ub_n = ~sram_mask[1];
assign sram_lb_n = ~sram_mask[0];

reg [31:0] mem_rdata_r;
assign mem_rdata = mem_rdata_r;

reg mem_ready_r;
assign mem_ready = mem_ready_r;

reg [18:0] sram_addr_reg;
assign sram_addr = sram_addr_reg[18:0];

reg [2:0 ] sram_state;

localparam sram_idle = 'd0;
localparam sram_transmit0 = 'd1;
localparam sram_transmit1 = 'd2;

localparam sram_write_cnt = 'd1;
localparam sram_read_cnt = 'd1;
reg [3:0] delay_cnt;
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        wr <= 'b0;
        sram_oe <= 'b0;
        mem_ready_r <= 'b0;
        sram_mask <= 'b00;
        sram_state <= sram_idle;
        sram_wdata <= 'h0000;
        sram_addr_reg[18:0] <= 'd0;
        mem_rdata_r <= 'h0000_0000_0000_0000;
    end
    else begin
        case(sram_state)
            sram_idle:begin
                sram_state <= sram_idle;
                if(mem_valid&&(!mem_ready)) begin
                    sram_state <= sram_transmit0;
                    if(mem_wstrb != 'b0000) begin
                        wr <= 'b1;
                        sram_oe <= 'b0;
                        delay_cnt <= 'd0;
                        case(mem_wstrb)
                            'b0001:begin
                                sram_addr_reg[18:0] <= {mem_addr[19:2],1'b0};
                                sram_mask <= 'b01;
                                sram_wdata <= {'h00,mem_wdata[7:0]};
                            end
                            'b0010:begin
                                sram_addr_reg[18:0] <= {mem_addr[19:2],1'b0};
                                sram_mask <= 'b10;
                                sram_wdata <= {mem_wdata[15:8],'h00};
                            end
                            'b0100:begin
                                sram_addr_reg[18:0] <= {mem_addr[19:2],1'b1};
                                sram_mask <= 'b01;
                                sram_wdata <= {mem_wdata[23:16],'h00};
                            end
                            'b1000:begin
                                sram_addr_reg[18:0] <= {mem_addr[19:2],1'b1};
                                sram_mask <= 'b10;
                                sram_wdata <= {mem_wdata[31:24],'h00};
                            end
                            'b0011,'b1111:begin
                                sram_addr_reg[18:0] <= {mem_addr[19:2],1'b0};
                                sram_mask <= 'b11;
                                sram_wdata <= mem_wdata[15:0];
                            end
                            'b11_00:begin
                                wr <= 'b1;
                                sram_addr_reg[18:0] <= {mem_addr[19:2],1'b1};
                                sram_mask <= 'b11;
                                sram_wdata <= mem_wdata[31:16];
                            end
                        endcase
                    end
                    else begin
                        sram_oe <= 'b1;
                        sram_mask <= 'b11;
                        sram_addr_reg[18:0] <= {mem_addr[19:2],1'b0};
                    end
                end
                else begin
                    delay_cnt <= 'd0;
                    wr <= 'b0;
                    sram_oe <= 'b1;
                    mem_ready_r <= 'b0;
                    sram_mask <= 'b00;
                    sram_state <= sram_idle;
                    sram_wdata <= 'h0000;
                    mem_rdata_r <= 'h0000_0000_0000_0000;
                end
            end
            sram_transmit0:begin
                sram_state <= sram_state;
                mem_ready_r <= 'b0;
                delay_cnt <= delay_cnt + 'b1;
                if(mem_wstrb != 'b0000)begin
                    wr <= 'b0;
                    sram_addr_reg[18:0] <= sram_addr_reg[18:0];
                    sram_wdata <= sram_wdata;
                    if(delay_cnt == sram_write_cnt) begin
                        delay_cnt <= 'd0;
                        case(mem_wstrb)
                            'b0001,'b0010,'b0100,'b1000,'b00_11,'b11_00:begin
                                sram_mask <= 'b00;
                                sram_oe <= 'b0;
                                wr <= 'b0;
                                mem_ready_r <= 1'b1;
                                sram_state <= sram_idle;
                            end
                            'b11_11:begin
                                wr <= 'b1;
                                sram_oe <= 'b0;
                                sram_addr_reg[18:0] <= {mem_addr[19:2],1'b1};
                                sram_mask <= 'b11;
                                sram_wdata <= mem_wdata[31:16];
                                sram_state <= sram_transmit1;
                                mem_ready_r <= 'b0;
                            end
                        endcase
                    end
                end
                else begin
                    sram_addr_reg[18:0] <= sram_addr_reg[18:0];
                    sram_mask <= 'b11;
                    sram_oe <= 'b1;
                    mem_ready_r <= 'b0;
                    delay_cnt <= delay_cnt + 'b1;
                    if(delay_cnt == sram_read_cnt) begin
                        delay_cnt <= 'd0;
                        sram_addr_reg[18:0] <= {mem_addr[19:2],1'b1};
                        sram_state <= sram_transmit1;
                        mem_rdata_r[31:0] <= {'hffff,sram_data[15:0]};
                    end
                    else begin
                        
                    end
                end
            end
            sram_transmit1:begin
                mem_ready_r <= 'b0;
                sram_oe <= 'b1;
                delay_cnt <= delay_cnt + 'b1;
                sram_state <= sram_transmit1;
                if(mem_wstrb == 'b1111) begin
                    sram_addr_reg[18:0] <= sram_addr_reg[18:0];
                    sram_wdata <= sram_wdata;
                    sram_mask <= 'b00;
                    sram_oe <= 'b1;
                    wr <= 'b0;
                    if(delay_cnt == sram_write_cnt) begin
                        sram_wdata <= 'h0000;
                        mem_ready_r <= 'b1;
                        sram_state <= sram_idle;
                    end
                end
                else begin
                    if(delay_cnt == sram_read_cnt) begin
                        delay_cnt <= 'd0;
                        mem_ready_r <= 'b1;
                        sram_state <= sram_idle;
                        mem_rdata_r[31:0] <= {sram_data[15:0],mem_rdata_r[15:0]};
                    end
                    else begin
                        sram_addr_reg[18:0] <= sram_addr_reg[18:0];
                        sram_wdata <= sram_wdata;
                         
                    end
                end
            end
        endcase
    end
end

endmodule